package com.func.domain.strategy.service;

import com.func.domain.strategy.model.entity.RaffleAwardEntity;
import com.func.domain.strategy.model.entity.RaffleFactorEntity;
import com.func.domain.strategy.model.entity.StrategyAwardEntity;
import com.func.domain.strategy.repository.IStrategyRepository;
import com.func.domain.strategy.service.armory.IStrategyDispatch;
import com.func.domain.strategy.service.rule.chain.factory.DefaultLogicChainFactory;
import com.func.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import com.func.types.enums.ResponseCode;
import com.func.types.exception.AppException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;

/**
 * @ClassName AbstractRaffleStrategy
 * @Description 策略抽奖抽象类
 * @Author: func
 * @Date 2025/2/26 9:08
 * @Version 1.0
 */

@Slf4j
@AllArgsConstructor
public abstract class AbstractRaffleStrategy implements IRaffleStrategy{
    // 策略仓储服务 -> 提供了与Redis, Mysql等存储层面的交互
    protected IStrategyRepository repository;
    // 策略调度服务 -> 只负责抽奖职责, 隔离职责, 不需要使用方关心或者调用抽奖功能的初始化
    protected IStrategyDispatch strategyDispatch;

    protected DefaultLogicChainFactory logicChainFactory;
    protected DefaultTreeFactory treeFactory;


    @Override
    public RaffleAwardEntity performRaffle(RaffleFactorEntity raffleFactorEntity) {
        // 1. 参数校验
        String userId = raffleFactorEntity.getUserId();
        Long strategyId = raffleFactorEntity.getStrategyId();
        if (null == strategyId || StringUtils.isBlank(userId))  {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
        }

        // 2. 从责任链工厂中获取责任链, 并执行抽奖
        DefaultLogicChainFactory.StrategyAwardVO chainStrategyAwardVO = this.raffleLogicChain(userId, strategyId);
        // 判断这个奖品是走的默认抽奖, 还是别的前置抽奖规则, 如果是前置规则不走中后置过滤
        log.info("抽奖策略计算-责任链 {} {} {} {}", userId, strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getAwardRuleValue());
        if (!DefaultLogicChainFactory.LogicModel.RULE_DEFAULT.getCode().equals(chainStrategyAwardVO.getAwardRuleValue())) {
            return buildRaffleAwardEntity(strategyId, chainStrategyAwardVO.getAwardId(), chainStrategyAwardVO.getAwardRuleValue());
        }

        // 3. 执行中置后置规则树过滤
        DefaultTreeFactory.StrategyAwardVO treeStrategyAwardVO = this.raffleLogicTree(userId, strategyId, chainStrategyAwardVO.getAwardId());
        log.info("抽奖策略计算-规则树 {} {} {} {}", userId, strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue());

        //4. 消费

        // 4. 返回抽奖结果
        return buildRaffleAwardEntity(strategyId, treeStrategyAwardVO.getAwardId(), treeStrategyAwardVO.getAwardRuleValue());
    }


    private RaffleAwardEntity buildRaffleAwardEntity(Long strategyId, Integer awardId, String awardConfig) {
       StrategyAwardEntity strategyAwardEntity =  repository.queryStrategyAward(strategyId, awardId);
       return RaffleAwardEntity.builder()
              .awardId(awardId)
              .awardConfig(awardConfig)
              .sort(strategyAwardEntity.getSort())
               .awardTitle(strategyAwardEntity.getAwardTitle())
              .build();
    }

    /**
     * 执行抽奖前过滤的抽奖
     * @param userId
     * @param strategyId
     * @return 抽到的奖品, 在这个位置只为awardId赋值了
     */
    public abstract DefaultLogicChainFactory.StrategyAwardVO raffleLogicChain(String userId, Long strategyId);

    /**
     * 执行抽奖中后过滤
     * @param userId
     * @param strategyId
     * @param awardId
     * @return 抽到的奖品
     */
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId);
    public abstract DefaultTreeFactory.StrategyAwardVO raffleLogicTree(String userId, Long strategyId, Integer awardId, Date endDateTime);
}
